package com.shiny.concurrency4java.atomic;

import com.shiny.concurrency4java.annoations.ThreadSafe;
import com.shiny.concurrency4java.util.Constant;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

@ThreadSafe
@Slf4j
public class AtomicLock {

    private AtomicInteger atomicI = new AtomicInteger(0);
    private int i = 0;

    public static void main(String[] args) throws Exception{
        final AtomicLock cas = new AtomicLock();
        ExecutorService executorService = Executors.newCachedThreadPool();
        final Semaphore semaphore = new Semaphore(Constant.threadTotal);
        final CountDownLatch countDownLatch = new CountDownLatch(Constant.clientTotal);
        long start = System.currentTimeMillis();
        for( int i = 0; i < Constant.clientTotal; i++ ){
            executorService.execute(()->{
                try {
                    semaphore.acquire();
                    cas.count();
                    cas.safeCount();
                    semaphore.release();

                }catch (Exception e) {
                    e.printStackTrace();
                }
                countDownLatch.countDown();

            });
        }
        countDownLatch.await();
        executorService.shutdown();
        log.info("cas i:{}",cas.i);
        log.info("cas atomicI:{}",cas.atomicI.get());
        log.info("intervalTime:{}",System.currentTimeMillis() - start);
        return;
    }

    private void safeCount(){
        for(;;){
            int i = atomicI.get();
            boolean suc = atomicI.compareAndSet(i,++i);
            if (suc){
                break;
            }
        }
    }

    private void count(){
        i++;
    }

    private void atomicThreadList(final AtomicLock cas) {
        List<Thread> ts = new ArrayList<Thread>(600);
        for(int j = 0; j < 100; j++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    for(int i = 0; i < 10000; i++) {
                        cas.count();
                        cas.safeCount();
                    }
                }
            });
            ts.add(t);
        }
        for(Thread t:ts){
            t.start();
        }
        // 等待所有线程执行完成
        for(Thread t:ts){
            try{
                t.join();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }

}
